package com.magina.common.utils;

import com.google.common.collect.Lists;
import com.magina.common.model.TestSortInnerDeepModel;
import com.magina.common.model.TestSortInnerModel;
import com.magina.common.model.TestSortModel;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.*;

/**
 *  实现了对象List的排序.
 *  实现了对象层级List的排序
 */
public class ListSortUtils {

        public static <E> void sort(List<E> list, final boolean isAsc, final String... sortnameArr) {
            Collections.sort(list, (a, b) -> {
                int ret = 0;
                try {
                    for (int i = 0; i < sortnameArr.length; i++) {
                        ret = ListSortUtils.compareObject(sortnameArr[i], isAsc, a, b);
                        if (0 != ret) {
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return ret;
            });
        }

        public static <E> void sort(List<E> list, final List<String> sortnameArr, final List<Boolean> typeArr) {
            if (sortnameArr.size() != typeArr.size()) {
                throw new RuntimeException("属性数组元素个数和升降序数组元素个数不相等");
            }
            Collections.sort(list, (a, b) -> {
                int ret = 0;
                try {
                    for (int i = 0; i < sortnameArr.size(); i++) {
                        ret = ListSortUtils.compareObject(sortnameArr.get(i), typeArr.get(i), a, b);
                        if (0 != ret) {
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return ret;
            });
        }


        private static <E> int compareObject(final String sortname, final boolean isAsc, E a, E b) throws Exception {
            int reCompareTo;
            Object value1 = ListSortUtils.forceGetFieldValue(a, sortname);
            Object value2 = ListSortUtils.forceGetFieldValue(b, sortname);
            //判空逻辑
            if(null == value1 )return 0;
            if(null == value2 )return 1;
            String str1 = value1.toString();
            String str2 = value2.toString();
            if (value1 instanceof Number && value2 instanceof Number) {
                int maxlen = Math.max(str1.length(), str2.length());
                str1 = ListSortUtils.addZero2Str((Number) value1, maxlen);
                str2 = ListSortUtils.addZero2Str((Number) value2, maxlen);
            } else if (value1 instanceof Date && value2 instanceof Date) {
                long time1 = ((Date) value1).getTime();
                long time2 = ((Date) value2).getTime();
                int maxlen = Long.toString(Math.max(time1, time2)).length();
                str1 = ListSortUtils.addZero2Str(time1, maxlen);
                str2 = ListSortUtils.addZero2Str(time2, maxlen);
            } else if (str1.endsWith("%") && str2.endsWith("%")) {
                //判定百分比 排序
                str1 = str1.replace("%","").trim();
                str2 = str2.replace("%","").trim();
                Double str1Double = Double.parseDouble(str1);
                Double str2Double = Double.parseDouble(str2);
                return isAsc ? str1Double.compareTo(str2Double) : str2Double.compareTo(str1Double);
            }
            return isAsc ? str1.compareTo(str2) :str2.compareTo(str1);
        }

        public static String addZero2Str(Number numObj, int length) {
            NumberFormat nf = NumberFormat.getInstance();
            // 设置是否使用分组
            nf.setGroupingUsed(false);
            // 设置最大整数位数
            nf.setMaximumIntegerDigits(length);
            // 设置最小整数位数
            nf.setMinimumIntegerDigits(length);
            return nf.format(numObj);
        }

        public static Object forceGetFieldValue(Object obj, String fieldName) throws Exception {
            //获取层级对象的属性
            if(fieldName.contains(".")){
                String[] strList = fieldName.split("\\.");
                for (int i = 0; i < strList.length; i++) {
                    Object innerObject  = forceGetFieldValue(obj,strList[i]);
                    return forceGetFieldValue(innerObject,strList[i+1]);
                }
            }
            if(null != fieldName && fieldName.length() > 0){
                fieldName  = CamelToUnderlineUtils.underlineToCamel(fieldName);
            }
            StringBuffer buffer=new StringBuffer();
            buffer.append("get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1));
            Method method = obj.getClass().getMethod(buffer.toString());
            return method.invoke(obj);
        }

        public static <T> int getSize(Iterable<T> iterable){
            if (iterable instanceof Collection) {
                return ((Collection<?>) iterable).size();
            } else {
                int count = 0;
                Iterator iterator = iterable.iterator();
                while(iterator.hasNext()) {
                    iterator.next();
                    count++;
                }
                return count;
            }
        }



 static List<TestSortModel> generateData() {
     List<TestSortModel> list = Lists.newArrayList();
     for (int i = 1; i < 6; i++) {
         TestSortInnerDeepModel innerDeepModel = TestSortInnerDeepModel.builder()
                 .dateInnerDeepColumn(new Date(System.currentTimeMillis()+i*5000))
                 .intInnerDeepColumn(333+i)
                 .strInnerDeepColumn("深度内部排序"+i)
                 .build();
         TestSortInnerModel innerModel = TestSortInnerModel.builder().intInnerColumn(222+i)
                 .strInnerColumn("内部排序"+i)
                 .dateInnerColumn(new Date(System.currentTimeMillis()+i*1000))
                 .innerDeepModel(innerDeepModel)
                 .build();
         TestSortModel model =  new TestSortModel(Integer.valueOf("111"+i),i, "排序"+i,new Date(System.currentTimeMillis()+i*2000),Long.valueOf((1000+i)),(long)(i+1000),Double.valueOf((2000+i)),(double)(2000+i),new BigDecimal(i+300),innerModel);
         list.add(model);
     }

     return list;
        }

    public static void main(String[] args) {
        List<TestSortModel> models = generateData();
        System.out.println("init");
        //实体字段排序
        System.out.println("====> Integer 字段排序");
        ListSortUtils.sort(models,false,"integerColmn");
        models.stream().forEach(p -> System.out.println(p.toString()));
//        System.out.println("====> int 字段排序");
//        ListUtils.sort(models,true,"intColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));
//        System.out.println("====> String 字段排序");
//        ListUtils.sort(models,false,"strColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));
//
//        System.out.println("====> Date 字段排序");
//        ListUtils.sort(models,true,"dateColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));

//        System.out.println("====> Long 字段排序");
//        ListUtils.sort(models,false,"aLongColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));

//        System.out.println("====> DoubleColumn 字段排序");
//        ListUtils.sort(models,true,"aDoubleColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));
//
//        System.out.println("====> BigDecimal 字段排序");
//        ListUtils.sort(models,false,"bigDecimalColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));
        // 内部对象 属性排序
//        System.out.println("====> inner int 字段排序");
//        ListUtils.sort(models,true,"innerModel.intInnerColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));
//
//        System.out.println("====> inner String 字段排序");
//        ListUtils.sort(models,false,"innerModel.strInnerColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));
//
//        System.out.println("====> inner Date 字段排序");
//        ListUtils.sort(models,true,"innerModel.dateInnerColumn");
//        models.stream().forEach(p -> System.out.println(p.toString()));

        // 深度内部对象 属性排序
        System.out.println("====> deep inner int 字段排序");
        ListSortUtils.sort(models,true,"innerModel.innerDeepModel.intInnerDeepColumn");
        models.stream().forEach(p -> System.out.println(p.toString()));

    }
}
